/**
 * created by 小卷毛, 2019-09-19 019
 * Copyright (c) 2019, 416143467@qq.com All Rights Reserved.
 * #                   *********                            #
 * #                  ************                          #
 * #                  *************                         #
 * #                 **  ***********                        #
 * #                ***  ****** *****                       #
 * #                *** *******   ****                      #
 * #               ***  ********** ****                     #
 * #              ****  *********** ****                    #
 * #            *****   ***********  *****                  #
 * #           ******   *** ********   *****                #
 * #           *****   ***   ********   ******              #
 * #          ******   ***  ***********   ******            #
 * #         ******   **** **************  ******           #
 * #        *******  ********************* *******          #
 * #        *******  ******************************         #
 * #       *******  ****** ***************** *******        #
 * #       *******  ****** ****** *********   ******        #
 * #       *******    **  ******   ******     ******        #
 * #       *******        ******    *****     *****         #
 * #        ******        *****     *****     ****          #
 * #         *****        ****      *****     ***           #
 * #          *****       ***        ***      *             #
 * #            **       ****        ****                   #
 */
package com.sgcc.pda.mdrh.task.common_ui.helper

import android.content.Context
import android.util.Base64
import com.google.gson.Gson
import java.io.*

/**
 * SharedPreferences工具类
 * <p> 单例和扩展两种调用方式 </p>
 */
object PreferencesHelper {

    var PREFERENCE_NAME: String = "sharedCommon"

    private fun getShared(context: Context) =
        context.getSharedPreferences(
            PREFERENCE_NAME,
            Context.MODE_PRIVATE
        )

    fun <T : Any> put(context: Context, key: String, value: T): Boolean {
        val editor = getShared(context).edit()
        when (value) {
            is String -> editor.putString(key, value)
            is Int -> editor.putInt(key, value)
            is Boolean -> editor.putBoolean(key, value)
            is Float -> editor.putFloat(key, value)
            is Long -> editor.putLong(key, value)
            else -> return false
        }
        return editor.commit()
    }

    fun <T : Serializable> putData(context: Context, key: String, value: T) {
        try {
            val baos = ByteArrayOutputStream()
            val oos = ObjectOutputStream(baos)
            oos.writeObject(value)
            val valueBase64 = String(Base64.encode(baos.toByteArray(), 0))
            val editor = getShared(context).edit()
            editor.putString(key, valueBase64)
            editor.apply()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    fun <T : Any> get(context: Context, key: String, defalutValue: T): T {
        val settings = getShared(context)
        @Suppress("UNCHECKED_CAST")
        return when (defalutValue) {
            is String -> settings.getString(key, defalutValue) as T
            is Int -> settings.getInt(key, defalutValue) as T
            is Boolean -> settings.getBoolean(key, defalutValue) as T
            is Float -> settings.getFloat(key, defalutValue) as T
            is Long -> settings.getLong(key, defalutValue) as T
            else -> defalutValue
        }
    }

    fun <T : Serializable> getData(context: Context, key: String): T? {
        val settings = getShared(context)
        try {
            val base64 = settings.getString(key, "").orEmpty()
            if (base64.isEmpty()) return null
            val bais = ByteArrayInputStream(Base64.decode(base64.toByteArray(), 1))
            @Suppress("UNCHECKED_CAST")
            return ObjectInputStream(bais).readObject() as T
        } catch (e: IOException) {
            e.printStackTrace()
            return null
        }
    }

    fun has(context: Context, key: String) = getShared(context).contains(key)

    fun remove(context: Context, key: String): Boolean {
        val editor = getShared(context).edit()
        editor.remove(key)
        return editor.commit()
    }

    fun clear(context: Context): Boolean {
        val editor = getShared(context).edit()
        editor.clear()
        return editor.commit()
    }

}

inline fun <reified T : Any> Context.putValue(key: String, value: T): Boolean {
    val settings = getSharedPreferences(
        PreferencesHelper.PREFERENCE_NAME,
        Context.MODE_PRIVATE
    )
    val editor = settings.edit()
    when (value) {
        is String -> editor.putString(key, value)
        is Int -> editor.putInt(key, value)
        is Boolean -> editor.putBoolean(key, value)
        is Float -> editor.putFloat(key, value)
        is Long -> editor.putLong(key, value)
        else -> return false
    }
    return editor.commit()
}

inline fun <reified T : Any> Context.putSharedData(key: String, value: T) {
    val settings = getSharedPreferences(
        PreferencesHelper.PREFERENCE_NAME,
        Context.MODE_PRIVATE
    )
    val editor = settings.edit()
    editor.putString(key, Gson().toJson(value))
    editor.apply()
}

inline fun <reified T : Any> Context.getValue(key: String, defalutValue: T): T {
    val settings = getSharedPreferences(
        PreferencesHelper.PREFERENCE_NAME,
        Context.MODE_PRIVATE
    )
    @Suppress("UNCHECKED_CAST")
    return when (defalutValue) {
        is String -> settings.getString(key, defalutValue) as T
        is Int -> settings.getInt(key, defalutValue) as T
        is Boolean -> settings.getBoolean(key, defalutValue) as T
        is Float -> settings.getFloat(key, defalutValue) as T
        is Long -> settings.getLong(key, defalutValue) as T
        else -> defalutValue
    }
}

inline fun <reified T : Any> Context.getSharedData(key: String): T? {
    val settings = getSharedPreferences(
        PreferencesHelper.PREFERENCE_NAME,
        Context.MODE_PRIVATE
    )
    val value = settings.getString(key, "").orEmpty()
    if (value.isEmpty()) return null
    return Gson().fromJson(value, T::class.java)
}

@Suppress("NOTHING_TO_INLINE")
inline fun Context.hasValue(key: String) =
    getSharedPreferences(
        PreferencesHelper.PREFERENCE_NAME,
        Context.MODE_PRIVATE
    ).contains(key)

@Suppress("NOTHING_TO_INLINE")
inline fun Context.removeValue(key: String): Boolean {
    val settings = getSharedPreferences(
        PreferencesHelper.PREFERENCE_NAME,
        Context.MODE_PRIVATE
    )
    val editor = settings.edit()
    editor.remove(key)
    return editor.commit()
}

@Suppress("NOTHING_TO_INLINE")
inline fun Context.clearValues(): Boolean {
    val settings = getSharedPreferences(
        PreferencesHelper.PREFERENCE_NAME,
        Context.MODE_PRIVATE
    )
    val editor = settings.edit()
    editor.clear()
    return editor.commit()
}